package com.lwl.java.base;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author lwl
 * @Description 两个线程交替打印奇偶数
 * @date 2025/9/6 15:49
 */
public class AlternatePrintingTwoThread {

    private int printNumber = 1;

    private Object lockObj = new Object();

    private Lock lock = new ReentrantLock();

    private Condition oddCondition = lock.newCondition();

    private Condition evenCondition = lock.newCondition();

    public static void main(String[] args) {
//        test01();
        AlternatePrintingTwoThread alternatePrintingTwoThread = new AlternatePrintingTwoThread();
        new Thread(alternatePrintingTwoThread::printOdd).start();
        new Thread(alternatePrintingTwoThread::printEven).start();
    }

    private void printOdd() {
        while (printNumber <= 100) {
            lock.lock();
            try {
                // 使用while循环检查条件，防止虚假唤醒
                while (printNumber % 2 == 0) { // 当前是偶数，奇数线程等待
                    oddCondition.await();
                }
                if (printNumber <= 100) { // 再次检查，因为可能在等待后数值已超限
                    System.out.println(Thread.currentThread().getName() + " : " + printNumber);
                    printNumber++;
                }
                evenCondition.signal(); // 唤醒等待在偶数条件上的线程
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态
                System.out.println("奇数线程被中断");
                break;
            } finally {
                lock.unlock();
            }
        }
    }

    private void printEven() {
        while (printNumber <= 100) {
            lock.lock();
            try {
                // 使用while循环检查条件，防止虚假唤醒
                while (printNumber % 2 == 1) { // 当前是奇数，偶数线程等待
                    evenCondition.await();
                }
                if (printNumber <= 100) { // 再次检查，因为可能在等待后数值已超限
                    System.out.println(Thread.currentThread().getName() + " : " + printNumber);
                    printNumber++;
                }
                oddCondition.signal(); // 唤醒等待在奇数条件上的线程
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态
                System.out.println("偶数线程被中断");
                break;
            } finally {
                lock.unlock();
            }
        }
    }

    private static void test01() {
        AlternatePrintingTwoThread alternatePrintingTwoThread = new AlternatePrintingTwoThread();
        new Thread(() -> {
            alternatePrintingTwoThread.printNumber(true);
        }).start();
        new Thread(() -> {
            alternatePrintingTwoThread.printNumber(false);
        }).start();
    }

    private void printNumber(boolean isOdd) {
        while (printNumber <= 100) {
            synchronized (lockObj) {
                while ((printNumber % 2 == 1 && !isOdd) || (printNumber % 2 == 0) && isOdd) {
                    try {
                        lockObj.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                if (printNumber >= 100) {
                    break;
                }
                System.out.println(Thread.currentThread().getName() + " 输出 ： " + printNumber++);
                lockObj.notifyAll();
            }
        }
    }

}
